package com.googlecode.mapperdao

import jdbc.Setup
import org.scalatest.FunSuite
import org.scalatest.matchers.ShouldMatchers
import org.junit.runner.RunWith
import org.scalatest.junit.JUnitRunner

/**
 * @author kkougios
 */
@RunWith(classOf[JUnitRunner])
class OneToManyDeclarePrimaryKeysIssueSuite extends FunSuite with ShouldMatchers
{
	if (Setup.database == "h2") {
		val (jdbc, mapperDao, _) = Setup.setupMapperDao(TypeRegistry(ProductEntity, PropertyEntity))

		test("insert") {
			createTables()
			val p1 = Product("p1", List(Property("pro1", "val1"), Property("pro2", "val2")))
			val i1 = mapperDao.insert(ProductEntity, p1)
			i1 should be(p1)
			mapperDao.select(ProductEntity, i1.id).get should be(i1)
		}

		test("update, same -many values for 2 products") {
			createTables()
			val p1 = Product("p1", List(Property("pro1", "val1"), Property("pro2", "val2")))
			val p2 = Product("p2", List(Property("pro1", "val1"), Property("pro2", "val2")))
			val List(i1, i2) = mapperDao.insertBatch(ProductEntity, List(p1, p2))

			val u2 = i2.copy(properties = i2.properties.filter(_.name == "pro1"))
			val up2 = mapperDao.update(ProductEntity, i2, u2)
			mapperDao.select(ProductEntity, i1.id).get should be(p1)
			mapperDao.select(ProductEntity, i2.id).get should be(up2)
		}

		test("update, change -many values for 2 products") {
			createTables()
			val p1 = Product("p1", List(Property("pro1", "val1"), Property("pro2", "val2")))
			val p2 = Product("p2", List(Property("pro1", "val1"), Property("pro2", "val2")))
			val List(i1, i2) = mapperDao.insertBatch(ProductEntity, List(p1, p2))

			val u1 = i1.copy(properties = i1.properties.filter(_.name == "pro2"))
			val u2 = i2.copy(properties = i2.properties.filter(_.name == "pro1"))
			val List(up1, up2) = mapperDao.updateBatch(ProductEntity, List((i1, u1), (i2, u2)))
			mapperDao.select(ProductEntity, i1.id).get should be(up1)
			mapperDao.select(ProductEntity, i2.id).get should be(up2)
		}

		test("deleting one of the main entities doesnt delete related data of the other") {
			createTables()
			val p1 = Product("p1", List(Property("pro1", "val1"), Property("pro2", "val2")))
			val p2 = Product("p2", List(Property("pro1", "val1"), Property("pro2", "val2")))
			val List(i1, i2) = mapperDao.insertBatch(ProductEntity, List(p1, p2))

			mapperDao.delete(ProductEntity, i1)
			mapperDao.select(ProductEntity, i1.id) should be(None)
			mapperDao.select(ProductEntity, i2.id).get should be(i2)
		}

		def createTables() {
			Setup.dropAllTables(jdbc)
			Setup.queries(this, jdbc).update("ddl")
		}
	}

	case class Product(name: String, properties: List[Property])

	case class Property(name: String, value: String)

	object ProductEntity extends Entity[Int, SurrogateIntId, Product]
	{
		val id = key("id") autogenerated (_.id)
		val name = column("name") to (_.name)
		val properties = onetomany(PropertyEntity) to (_.properties)

		def constructor(implicit m: ValuesMap) = new Product(name, properties) with Stored
		{
			val id: Int = ProductEntity.id
		}
	}

	object PropertyEntity extends Entity[String, NaturalStringId, Property]
	{
		val name = column("name") to (_.name)
		val value = column("value") to (_.value)

		declarePrimaryKey(name)

		def constructor(implicit m: ValuesMap) =
			new Property(name, value) with Stored
	}

}
